package services.api;

import com.avaje.ebean.Ebean;
import dto.api.ApiInfoDto;
import dto.api.ApiInputInfoDto;
import dto.api.ApiParamDto;
import models.application.*;
import models.user.AniUser;
import org.apache.commons.lang3.StringUtils;
import services.application.AniAppService;
import services.exception.AniDataException;
import services.exception.AniRuleException;
import utils.AniGeneralUtils;
import utils.AniPatternUtils;
import utils.MVCUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * User: yeh
 * Date: 2/14/13
 * Time: 10:42 PM
 * For:  wilddragon
 */
public class AniApiService {
    //api
    public static void checkApiNotExistence(AniApi oneApi){
        if(AniApi.getEntityNum(oneApi) > 0){
            throw new AniDataException("API_EXISTS");
        }
    }

    public static void checkApiExistence(AniApi oneApi){
        if(AniApi.getEntityNum(oneApi) < 1){
            throw new AniDataException("API_NOT_EXISTS");
        }
    }
    public static List<ApiInfoDto> getApiDtoListWithAppEntity(AniApp queryAppEntity){
        List<ApiInfoDto> apisDtoList = new ArrayList<ApiInfoDto>();

        for(AniApi oneApiDao: AniApi.findByHostApp(queryAppEntity)){
            apisDtoList.add(ApiInfoDto.generateFromDao(oneApiDao));
        }
        return apisDtoList;
    }
    public static List<AniApi> getApiWithEntity(ApiInputInfoDto oneApiQuery){
        List<AniApi> apis = null;
        try{
            if(oneApiQuery.id != null){
                apis = new ArrayList<AniApi>();
                apis.add(AniApi.getById(oneApiQuery.id));
            }else if(!StringUtils.isEmpty(oneApiQuery.apiName) && oneApiQuery.hostAppId != null){
                apis = AniApi.findByApiName(oneApiQuery.apiName, new AniApp(oneApiQuery.hostAppId));
            }else{
                throw new AniRuleException("API_QUERY_KEY_NOT_EXISTS");
            }
        } catch (Exception e){
            throw new AniDataException("API_QUERY_FAILED");
        }
        return apis;
    }
    protected static void checkApiRegisterElements(ApiInputInfoDto oneApiInputInfoDto, AniApp curApp, AniUser curUser){
        AniAppService.checkAppExistence(curApp);
        AniAppService.checkAppOwner(curUser, curApp);
        checkApiNotExistence(oneApiInputInfoDto.generateDao(curApp));
        checkApiInfoElementsFormatLegality(oneApiInputInfoDto);
    }
    protected static void checkApiUpdateElements(ApiInputInfoDto oneApiInputInfoDto, AniApp curApp, AniUser curUser){
        AniAppService.checkAppNotExistence(curApp);
        AniAppService.checkAppOwner(curUser, curApp);
        checkApiExistence(oneApiInputInfoDto.generateDao(curApp));
        checkApiInfoElementsFormatLegality(oneApiInputInfoDto);
    }
    private static void checkApiInfoElementsFormatLegality(ApiInputInfoDto oneApiInputInfoDto){
        String errMsg = null;
        if(!AniPatternUtils.isMatches(oneApiInputInfoDto.apiName, AniPatternUtils.APP_NAME_PATTERN)){
            errMsg = "API_NAME_ILLEGAL";
        }
        if(!AniPatternUtils.isMatches(oneApiInputInfoDto.url, AniPatternUtils.URL_PATTERN)){
            errMsg = "API_URL_ILLEGAL";
        }
        if(errMsg != null){
            throw new AniRuleException(errMsg);
        }
    }
    //param

    protected static void checkApiParamsNotDuplicated(List<String> apiParamNames){
        if(AniGeneralUtils.isListContainsDuplicateElement(apiParamNames)){
            throw new AniRuleException("INPUT_PARAM_NAMES_DUPLICATED");
        }
    }
    protected static void checkApiParamsNotExists(List<String> apiParamNames, AniApi hostApi){
        if(AniApiParam.getApiParamNumWithNames(hostApi, apiParamNames) > 0){
            throw new AniRuleException("API_PARAM_NAME_EXISTS");
        }
    }

    protected static void checkApiParamsIdExistence(List<ApiParamDto> apiParamsDto, AniApi hostApi){
        List<Long> updateParamsId = new ArrayList<Long>();
        for(ApiParamDto oneApiParam: apiParamsDto){
            updateParamsId.add(oneApiParam.id);
        }
        if(AniApiParam.getApiParamNumWithIds(updateParamsId, hostApi) < updateParamsId.size()){
            throw new AniRuleException("ONE_OR_MORE_IDS_NOT_EXIST_IN_CURRENT_API");
        }
    }
    protected static void checkApiParamElementsFormatLegality(ApiParamDto oneParamDto){
        String errMsg = null;
        if(!AniPatternUtils.isMatches(oneParamDto.paramName, AniPatternUtils.API_N_PARAM_NAME_PATTERN)){
            errMsg = "PARAM_NAME_ILLEGAL";
        }
        if(!StringUtils.isEmpty(oneParamDto.paramValue)
                && !AniPatternUtils.isMatches(oneParamDto.paramValue, AniPatternUtils.API_PARAM_VALUE_PATTERN)
                ){
            errMsg = "PARAM_DEFAULT_VALUE_ILLEGAL";
        }
        if(errMsg != null){
            throw new AniRuleException(errMsg);
        }
    }
    //api params
    protected static void saveApiParamsInfo(List<ApiParamDto> apiParams, AniApi hostApi){
        checkApiParamRegisterElements(apiParams, hostApi);
        saveApiParamsRegisterInfo(apiParams, hostApi);
    }
    private static void checkApiParamRegisterElements(List<ApiParamDto> apiParams, AniApi oneApi){
        checkApiExistence(oneApi);
        List<String> apiParamsName = ApiParamDto.getParamsName(apiParams);
        checkApiParamsNotDuplicated(apiParamsName);
        checkApiParamsNotExists(apiParamsName, oneApi);
        for(ApiParamDto oneParamDto: apiParams){
            MVCUtils.verifyRequiredElementsInObject(oneParamDto, ApiParamDto.requiredRegisterFieldKeys);
            checkApiParamElementsFormatLegality(oneParamDto);
        }
    }
    private static List<AniApiParam> saveApiParamsRegisterInfo(List<ApiParamDto> apiParamsDto, AniApi hostApi){
        List<AniApiParam> apiParams = ApiParamDto.getApiParamsDao(apiParamsDto, hostApi);
        System.out.println(apiParams.get(0).id);
        try{
            Ebean.save(apiParams);
        } catch (Exception e){
            throw new AniDataException("API_PARAM_INFO_SAVING_FAILED");
        }
        return apiParams;
    }
}